package com.wonders.framework.util.security;

import java.io.ByteArrayOutputStream;
import java.io.InputStream;
import java.security.KeyFactory;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.Signature;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;

import org.bouncycastle.util.encoders.Base64;

import com.wonders.framework.exception.FrameworkException;

/**
 * RSA签名算法工具
 * 
 * @author WuBin
 * 
 */
public class RsaUtil {

	/**
	 * 转换私钥
	 * 
	 * @param key
	 *            私钥字符
	 * @return 私钥
	 */
	public static PrivateKey parsePrivateKey(String key) {
		try {
			PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(
					Base64.decode(key));
			KeyFactory kf = KeyFactory.getInstance("RSA");
			return kf.generatePrivate(keySpec);
		} catch (Exception e) {
			throw new FrameworkException("转换私钥失败", e);
		}
	}

	/**
	 * 转换私钥
	 * 
	 * @param is
	 *            私钥文件流
	 * @return 私钥
	 */
	public static PrivateKey parsePrivateKey(InputStream is) {
		try {
			byte[] encodedKey = new byte[is.available()];
			is.read(encodedKey);
			PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(encodedKey);
			KeyFactory kf = KeyFactory.getInstance("RSA");
			return kf.generatePrivate(keySpec);
		} catch (Exception e) {
			throw new FrameworkException("转换私钥失败", e);
		}
	}

	/**
	 * 签名
	 * 
	 * @param privateKey
	 *            私钥
	 * @param data
	 *            待签名数据
	 * @return 签名数据
	 */
	public static byte[] sign(PrivateKey privateKey, byte[]... data) {
		try {
			Signature signObject = Signature.getInstance("Sha1WithRSA");
			signObject.initSign(privateKey);
			ByteArrayOutputStream baos = new ByteArrayOutputStream();
			for (byte[] sub : data) {
				if (sub != null) {
					baos.write(sub);
				}
			}
			signObject.update(baos.toByteArray());
			return signObject.sign();
		} catch (Exception e) {
			throw new FrameworkException("签名失败", e);
		}
	}

	/**
	 * 转换公钥
	 * 
	 * @param key
	 *            公钥字符
	 * @return 公钥
	 */
	public static PublicKey parsePublicKey(String key) {
		try {
			X509EncodedKeySpec keySpec = new X509EncodedKeySpec(
					Base64.decode(key));
			KeyFactory kf = KeyFactory.getInstance("RSA");
			return kf.generatePublic(keySpec);
		} catch (Exception e) {
			throw new FrameworkException("转换公钥失败", e);
		}
	}

	/**
	 * 验签
	 * 
	 * @param publicKey
	 *            公钥
	 * @param sign
	 *            签名
	 * @param data
	 *            待验签数据
	 * @return 是否通过
	 */
	public static boolean verify(PublicKey publicKey, byte[] sign,
			byte[]... data) {
		try {
			Signature signObject = Signature.getInstance("Sha1WithRSA");
			signObject.initVerify(publicKey);
			ByteArrayOutputStream baos = new ByteArrayOutputStream();
			for (byte[] sub : data) {
				if (sub != null) {
					baos.write(sub);
				}
			}
			signObject.update(baos.toByteArray());
			return signObject.verify(sign);
		} catch (Exception e) {
			throw new FrameworkException("验签失败", e);
		}
	}

}
